﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Collections;
using System.Linq;
using System.Text;

namespace tab2sql
{

    public class Series
    {

        public Series(string input)
        {
            
            mySeries = input.Split('\n');
            CopyArraysSafely(ref myNumbers, mySeries);
            Count = getCount();
            DistinctCount = getDistinctCount();
            finalMessage.AppendLine("This series contains " + Count.ToString() + " elements");
            finalMessage.AppendLine("This series contains " + DistinctCount.ToString() + " unique elements");
            finalMessage.AppendLine(Environment.NewLine);
            finalMessage.AppendLine("Longest value is " + getLongestLine() + " ");
            finalMessage.AppendLine("Shortest value is " + getShortestLine() + " ");
            finalMessage.AppendLine("Combined Length is  " + getCombinedLength() + " ");
            finalMessage.AppendLine(Environment.NewLine);
            finalMessage.AppendLine("Total : " + String.Format("{0:n}", getTotal()));
            finalMessage.AppendLine("Average : " + getMean());

            finalMessage.AppendLine("Largest value is " + getLargest().ToString() + " ");
            finalMessage.AppendLine("Smallest value is " + getSmallest().ToString() + " ");

            finalMessage.AppendLine(Environment.NewLine);
            finalMessage.AppendLine(Environment.NewLine);
            finalMessage.AppendLine("Most common value is " + getMostFrequent() + " ");
            finalMessage.AppendLine("Dupes list : " + Environment.NewLine + Dupes);
            finalMessage.AppendLine(Environment.NewLine);
            //finalMessage.AppendLine("Valid Post Code: " + getHowManyPostCodes().ToString());
            //finalMessage.AppendLine(notPostCodes);
        }


        public string[] mySeries = new string[3000];
        public double[] myNumbers = new double[3000];
        public int Count = -1;
        public int DistinctCount = -1;
        public int Largest = -1;
        public int Smallest = -1;
        public int Mean = -1;
        public double Total = -1;
        public int Median = -1;
        public int Mode = -1;
        public string Dupes = "";
        public string notPostCodes = "";
        public StringBuilder finalMessage = new StringBuilder();
        

        private int getLargest()
        {
            int Biggest = 0;
            foreach (int x in myNumbers)
            {
                if (x > Biggest)
                {
                    Biggest = x;
                }
            }
            return Biggest;
        }

        private double getTotal()
        {
            double Total = 0;
            foreach (double x in myNumbers)
            {
                Total += x;
            }

            return Total;
        }

        private double getSmallest()
        {
            double Smallest = 999999999;
            foreach (double x in myNumbers)
            {
                if (x < Smallest && x != 0)
                {
                    Smallest = x;
                }
            }
            return Smallest;
        }

        private double getMean()
        {
            return getAverageFromDoubleArray(myNumbers);
            
        }
        
        private int getCount()
        {
            int ReturnValue = 0;
            int i = 0;
            foreach (string myValue in mySeries)
            {
                if (myValue != null && myValue.Length > 0)
                {
                    i++;
                }
            }

            ReturnValue = i;
            return ReturnValue;
        }
        private int getDistinctCount()
        {
            string[] tmp = new string[mySeries.Count()+50];
            int ReturnValue = 0;
            int i = 0;
            foreach (string myValue in mySeries)
            {
                if (myValue != null && myValue.Length > 0)
                {
                    if (tmp.Contains(myValue))
                    {
                        //whatever
                    }
                    else { i++;
                    tmp[i] = myValue;
                    
                    }
                }
            }

            ReturnValue = i;
            return ReturnValue;
        }
        private string getLongestLine()
        {
            string[] tmp = new string[mySeries.Count()];
            string ReturnValue = "";
        
            int CurrentRecord = 0;
            int length = 0;
            foreach (string myValue in mySeries)
            {
                if (myValue != null && myValue.Length > 0)
                {
                    
                    length = myValue.Trim().Length;
                    if (length > CurrentRecord)
                    {
                        CurrentRecord = length;
                        ReturnValue = myValue;
                    }
                }
            }

            
            return ReturnValue;
        }
        private string getShortestLine()
        {
            string[] tmp = new string[mySeries.Count()];
            string ReturnValue = "";
           
            int CurrentRecord = 0;
            int length = 0;
            foreach (string myValue in mySeries)
            {
                if (myValue != null && myValue.Length > 0)
                {

                    length = myValue.Trim().Length;
                    if (length <CurrentRecord || CurrentRecord==0)
                    {
                        CurrentRecord = length;
                        ReturnValue = myValue;
                    }
                }
            }


            return ReturnValue;
        }
        private string getMostFrequent()
        {
            Hashtable Keys = new Hashtable();
            Hashtable Counts = new Hashtable();
            string rtnValue = "";
           
   
            foreach (string myValue in mySeries)
            {
                if (myValue != null && myValue.Length > 0)
                {
                    if (Keys.Contains(myValue.ToLower()))
                    {
                        Keys[myValue.ToLower()] = (int)Keys[myValue.ToLower()] + 1;
                    }
                    else
                    {
                        Keys.Add(myValue.ToLower(),0);
                    }
                }
            }
            int Popular = 0;
            foreach (string K in Keys.Keys)
            {
                if ((int)Keys[K.ToLower()] > Popular)
                {
                    Popular = (int)Keys[K.ToLower()];
                    rtnValue = K.ToLower();
                }
                if ((int)Keys[K] > 1)
                {
                    Dupes += K + " - " + (int)Keys[K] + " occurances"+Environment.NewLine;
                }
                
            }



            return rtnValue+" ("+Popular.ToString()+")";
        }
        private void CopyArraysSafely(ref double[] myNumbers, string[] mySeries)
        {
            int i = 0;
            foreach (string value in mySeries)
            {
                if (DTypes.IsStringDecimal(value))
                {
                    try
                    {
                        myNumbers[i] = Convert.ToDouble(value);
                        i++;
                    }
                    catch
                    {
                        // meh
                    }
                }

                
            }
           myNumbers = (double[])DGen.ResizeArray(myNumbers, i+1);
        }
        double getAverageFromDoubleArray(double[] dblArray)
        {
            double dblResult = 0;
            foreach (double dblValue in dblArray)
                dblResult += dblValue;
            return dblResult / dblArray.Length;
        }


        private int getCombinedLength()
        {
            string foo = "";
            foreach (string c in mySeries)
            {
                string c2 = c.Trim();
                foo += c2;
            }
            return foo.Length;
        }

        private int getHowManyPostCodes()
        {
            int runningTotal = 0;
            foreach (string x in mySeries)
            {
                if (DGen.IsValidPostCode(x))
                {
                    runningTotal++;
                }
                else
                {
                    notPostCodes += x + Environment.NewLine;
                }
            }

            return runningTotal;
        }



    }

}
